﻿// Decompiled with JetBrains decompiler
// Type: DnProcessSimulateCommands.Calibration.CApCalibrationTransformation
// Assembly: DnProcessSimulateCommands, Version=2402.0.0.890, Culture=neutral, PublicKeyToken=null
// MVID: A885D881-AEDF-447E-852A-6F13102E089C
// Assembly location: C:\Program Files\Tecnomatix_2402\eMPower\DotNetCommands\DnProcessSimulateCommands.dll

using EngineeringInternalExtension;
using System;
using System.Collections;
using System.Collections.ObjectModel;
using System.ComponentModel;
using Tecnomatix.Engineering;


namespace DnProcessSimulateCommands.Calibration;

public class CApCalibrationTransformation : INotifyPropertyChanged
{
  private ObservableCollection<CApCalibrationPair> _CalibrationPairList = new ObservableCollection<CApCalibrationPair>();
  private CApCalibrationPair _SelectedCalibrationPair;
  private TxFrame _RelativeToFrame;
  private TxTransformation _RelativeToTransformation;
  private TxTransformation _Transformation = new TxTransformation();
  private TxVector _TranslationOnly = new TxVector();
  private bool _IsMaintainOrientation;
  private double _MaximumDistance;
  private double _AverageDistance;
  private double _RootMeanSquare;
  private bool _AutoCalibrate;
  private TxCalibrationTransformationException _CalibrationException = TxCalibrationTransformationException.NoException;

  public event PropertyChangedEventHandler PropertyChanged;

  public ObservableCollection<CApCalibrationPair> CalibrationPairs
  {
    get => this._CalibrationPairList;
    set
    {
      this._CalibrationPairList = value;
      if (this.PropertyChanged == null)
        return;
      this.PropertyChanged((object) this, new PropertyChangedEventArgs(nameof (CalibrationPairs)));
    }
  }

  public CApCalibrationPair SelectedCalibrationPair
  {
    get => this._SelectedCalibrationPair;
    set
    {
      this._SelectedCalibrationPair = value;
      if (this.PropertyChanged == null)
        return;
      this.PropertyChanged((object) this, new PropertyChangedEventArgs(nameof (SelectedCalibrationPair)));
    }
  }

  public TxFrame RelativeToFrame
  {
    get => this._RelativeToFrame;
    set
    {
      this._RelativeToFrame = value;
      if (this.PropertyChanged != null)
        this.PropertyChanged((object) this, new PropertyChangedEventArgs(nameof (RelativeToFrame)));
      if (TxFrame.op_Inequality(this._RelativeToFrame, (ITxObject) null))
      {
        this.RelativeToTransformation = this._RelativeToFrame.AbsoluteLocation;
      }
      else
      {
        if (!TxTransformation.op_Equality(this.RelativeToTransformation, (TxTransformation) null))
          return;
        this.RelativeToTransformation = new TxTransformation();
      }
    }
  }

  public TxTransformation RelativeToTransformation
  {
    get => this._RelativeToTransformation;
    set
    {
      if (!TxTransformation.op_Inequality(this._RelativeToTransformation, value))
        return;
      this._RelativeToTransformation = value;
      if (this.PropertyChanged != null)
        this.PropertyChanged((object) this, new PropertyChangedEventArgs(nameof (RelativeToTransformation)));
      if (TxFrame.op_Inequality(this.RelativeToFrame, (ITxObject) null) && TxTransformation.op_Inequality(this.RelativeToFrame.AbsoluteLocation, this._RelativeToTransformation))
        this.RelativeToFrame = (TxFrame) null;
      this.UpdateRelativeLocation();
      this.Calibrate();
    }
  }

  public TxTransformation Transformation
  {
    get => this._Transformation;
    set
    {
      this._Transformation = value;
      if (this.PropertyChanged != null)
        this.PropertyChanged((object) this, new PropertyChangedEventArgs("MaintainTransformation"));
      this.UpdateCalibrationResult();
    }
  }

  public TxVector TranslationOnly
  {
    get => this._TranslationOnly;
    set
    {
      this._TranslationOnly = value;
      if (this.PropertyChanged != null)
        this.PropertyChanged((object) this, new PropertyChangedEventArgs("MaintainTransformation"));
      this.UpdateCalibrationResult();
    }
  }

  public bool IsMaintainOrientation
  {
    get => this._IsMaintainOrientation;
    set
    {
      this._IsMaintainOrientation = value;
      if (this.PropertyChanged != null)
        this.PropertyChanged((object) this, new PropertyChangedEventArgs("MaintainTransformation"));
      this.UpdateCalibrationResult();
    }
  }

  public TxTransformation MaintainTransformation
  {
    get
    {
      return this.IsMaintainOrientation ? new TxTransformation(this.TranslationOnly, new TxVector(), (TxTransformation.TxRotationType) 1) : this.Transformation;
    }
  }

  public double MaximumDistance
  {
    get => this._MaximumDistance;
    set
    {
      this._MaximumDistance = value;
      if (this.PropertyChanged == null)
        return;
      this.PropertyChanged((object) this, new PropertyChangedEventArgs(nameof (MaximumDistance)));
    }
  }

  public double AverageDistance
  {
    get => this._AverageDistance;
    set
    {
      this._AverageDistance = value;
      if (this.PropertyChanged == null)
        return;
      this.PropertyChanged((object) this, new PropertyChangedEventArgs(nameof (AverageDistance)));
    }
  }

  public double RootMeanSquare
  {
    get => this._RootMeanSquare;
    set
    {
      this._RootMeanSquare = value;
      if (this.PropertyChanged == null)
        return;
      this.PropertyChanged((object) this, new PropertyChangedEventArgs(nameof (RootMeanSquare)));
    }
  }

  public bool AutoCalibrate
  {
    get => this._AutoCalibrate;
    set => this._AutoCalibrate = value;
  }

  public TxCalibrationTransformationException CalibrationException
  {
    get => this._CalibrationException;
    set
    {
      this._CalibrationException = value;
      if (this.PropertyChanged == null)
        return;
      this.PropertyChanged((object) this, new PropertyChangedEventArgs(nameof (CalibrationException)));
    }
  }

  public void Clone(CApCalibrationTransformation origin)
  {
    this.CalibrationPairs = new ObservableCollection<CApCalibrationPair>();
    foreach (CApCalibrationPair calibrationPair in (Collection<CApCalibrationPair>) origin._CalibrationPairList)
    {
      CApCalibrationPair capCalibrationPair = new CApCalibrationPair();
      capCalibrationPair.Clone(calibrationPair);
      this.CalibrationPairs.Add(capCalibrationPair);
    }
    this.SelectedCalibrationPair = origin.SelectedCalibrationPair;
    this.Transformation = origin.Transformation;
    this.TranslationOnly = origin.TranslationOnly;
    this.RelativeToFrame = origin.RelativeToFrame;
    this.RelativeToTransformation = origin.RelativeToTransformation;
    this.AverageDistance = origin.AverageDistance;
    this.MaximumDistance = origin.MaximumDistance;
    this.RootMeanSquare = origin.RootMeanSquare;
    this.CalibrationException = origin.CalibrationException;
  }

  private void UpdateRelativeLocation()
  {
    foreach (CApCalibrationPair calibrationPair in (Collection<CApCalibrationPair>) this.CalibrationPairs)
      calibrationPair.RelativeToTransformation = this._RelativeToTransformation;
  }

  private void CalculateDistance()
  {
    foreach (CApCalibrationPair calibrationPair in (Collection<CApCalibrationPair>) this.CalibrationPairs)
    {
      calibrationPair.DistanceBefore = calibrationPair.Distance(new TxTransformation());
      calibrationPair.DistanceAfter = calibrationPair.Distance(this.MaintainTransformation);
    }
  }

  public TxVector CalculateTranslation()
  {
    TxVector translation = new TxVector();
    if (this.ActivatePairsCount() > 0)
    {
      TxVector txVector1 = new TxVector();
      TxVector txVector2 = new TxVector();
      foreach (CApCalibrationPair calibrationPair in (Collection<CApCalibrationPair>) this.CalibrationPairs)
      {
        if (calibrationPair.IsActive)
        {
          txVector1 = TxVector.op_Addition(txVector1, calibrationPair.ActualRelativeLocation.Translation);
          txVector2 = TxVector.op_Addition(txVector2, calibrationPair.VirtualRelativeLocation.Translation);
        }
      }
      translation = TxVector.op_Subtraction(TxVector.op_Division(txVector1, (double) this.ActivatePairsCount()), TxVector.op_Division(txVector2, (double) this.ActivatePairsCount()));
    }
    return translation;
  }

  private double CalculateMaximumDistance()
  {
    double maximumDistance = 0.0;
    foreach (CApCalibrationPair calibrationPair in (Collection<CApCalibrationPair>) this._CalibrationPairList)
    {
      if (calibrationPair.IsActive && maximumDistance < calibrationPair.DistanceAfter)
        maximumDistance = calibrationPair.DistanceAfter;
    }
    return maximumDistance;
  }

  private double CalculateAverageDistance()
  {
    double averageDistance = 0.0;
    if (this.ActivatePairsCount() > 0)
    {
      foreach (CApCalibrationPair calibrationPair in (Collection<CApCalibrationPair>) this._CalibrationPairList)
      {
        if (calibrationPair.IsActive)
          averageDistance += calibrationPair.DistanceAfter;
      }
      averageDistance /= (double) this.ActivatePairsCount();
    }
    return averageDistance;
  }

  private double CalculateRootMeanSquare()
  {
    double rootMeanSquare = 0.0;
    this.AverageDistance = this.CalculateAverageDistance();
    if (this.ActivatePairsCount() > 0)
    {
      foreach (CApCalibrationPair calibrationPair in (Collection<CApCalibrationPair>) this._CalibrationPairList)
      {
        if (calibrationPair.IsActive)
          rootMeanSquare += Math.Pow(calibrationPair.DistanceAfter - this.AverageDistance, 2.0);
      }
      rootMeanSquare = Math.Sqrt(rootMeanSquare / (double) this.ActivatePairsCount());
    }
    return rootMeanSquare;
  }

  public void AddPair(CApCalibrationPair cp)
  {
    cp.RelativeToTransformation = this.RelativeToTransformation;
    cp.Parent = this;
    this._CalibrationPairList.Add(cp);
    this.SelectedCalibrationPair = cp;
    this.Calibrate();
  }

  public void RemovePair(CApCalibrationPair cp)
  {
    this._CalibrationPairList.Remove(cp);
    this.Calibrate();
  }

  public void ClearPairs()
  {
    this._CalibrationPairList.Clear();
    this.Calibrate();
  }

  public void UpdateCalibrationResult()
  {
    this.CalculateDistance();
    this.MaximumDistance = this.CalculateMaximumDistance();
    this.AverageDistance = this.CalculateAverageDistance();
    this.RootMeanSquare = this.CalculateRootMeanSquare();
  }

  public void Calibrate()
  {
    if (!this.AutoCalibrate)
      return;
    ArrayList arrayList1 = new ArrayList();
    ArrayList arrayList2 = new ArrayList();
    foreach (CApCalibrationPair calibrationPair in (Collection<CApCalibrationPair>) this._CalibrationPairList)
    {
      if (calibrationPair.IsActive)
      {
        arrayList1.Add((object) calibrationPair.ActualRelativeLocation.Translation);
        arrayList2.Add((object) calibrationPair.VirtualRelativeLocation.Translation);
      }
    }
    try
    {
      this.TranslationOnly = this.CalculateTranslation();
      this.Transformation = TxCalibrationEx.CalibrationCreateTransformation(arrayList2, arrayList1);
      if (this.Transformation.Equals((object) new TxTransformation()))
        this.CalibrationException = TxCalibrationTransformationException.NoImprovement;
      else
        this.CalibrationException = TxCalibrationTransformationException.NoException;
    }
    catch (Exception ex)
    {
      this.Transformation = new TxTransformation();
      this.CalibrationException = TxCalibrationTransformationException.NoValidCalibration;
      if (ex == null)
        return;
      if (ex is TxCalibrationShouldGetAtLeast3PairsException)
        this.CalibrationException = TxCalibrationTransformationException.ShouldGetAtLeast3Pairs;
      if (ex is TxCalibrationVirtualPointsAreCollinearException)
        this.CalibrationException = TxCalibrationTransformationException.VirtualPointsAreCollinear;
      if (ex is TxCalibrationActualPointsAreCollinearException)
        this.CalibrationException = TxCalibrationTransformationException.ActualPointsAreCollinear;
      if (ex is TxCalibrationFailedNoConvergenceAfter30IterationsException)
        this.CalibrationException = TxCalibrationTransformationException.FailedNoConvergenceAfter30Iterations;
      if (ex is TxCalibrationFailedNoisyOrColinearInputPointsException)
        this.CalibrationException = TxCalibrationTransformationException.FailedNoisyOrColinearInputPoints;
      if (ex is TxCalibrationFailedNonOrthonormalResultException)
        this.CalibrationException = TxCalibrationTransformationException.FailedNonOrthonormalResult;
      if (ex is TxCalibrationFailedMirrorTransformationException)
        this.CalibrationException = TxCalibrationTransformationException.FailedMirrorTransformation;
      if (!(ex is TxCalibrationTheListsLenAreNotEqualException))
        return;
      this.CalibrationException = TxCalibrationTransformationException.TheListsLenAreNotEqual;
    }
  }

  private int ActivatePairsCount()
  {
    int num = 0;
    foreach (CApCalibrationPair calibrationPair in (Collection<CApCalibrationPair>) this._CalibrationPairList)
    {
      if (calibrationPair.IsActive)
        ++num;
    }
    return num;
  }

  public bool CheckIfLocationExists(ITxLocatableObject location)
  {
    foreach (CApCalibrationPair calibrationPair in (Collection<CApCalibrationPair>) this._CalibrationPairList)
    {
      if (calibrationPair.ActualPoint.Equals((object) location) || calibrationPair.VirtualPoint.Equals((object) location))
        return true;
    }
    return false;
  }
}
